package com.desire.codegenerator;

import cn.hutool.setting.dialect.Props;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.desire.codegenerator.filecreate.FileCreate;
import com.desire.codegenerator.outconfig.*;

import java.util.ArrayList;
import java.util.List;

public class CodeGenerator {
    private static  String controllerPath;
    private static  String servicePath;
    private  static  String serviceimplPath;
    private static  String mapperXmlPath;
    private static  String  mapperInterfacePath;
    private static String  entityPath;
    private static  String dsUrl;
    private static  String dsDriverName;
    private static  String dsUsername;
    private static  String dsPassword;
    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        //设置环境变量
        setEnv();
        // 全局配置
        mpg.setGlobalConfig(globalConfig());
        // 数据源配置
        mpg.setDataSource(datasourceConfig());
        // 包配置
        mpg.setPackageInfo(packageConfig());
        // 自定义配置
        InjectionConfig cfg = injectionConfig();
        // 自定义输出配置
        cfg.setFileOutConfigList(selfOutConfig());
        cfg.setFileCreate(fileCreate());
        mpg.setCfg(cfg);
        // 配置模板
        mpg.setTemplate(templateConfig());
        // 策略配置
        mpg.setStrategy(strategyConfig());
        //设置输出引擎为freemarker
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();
    }
    private static void setEnv(){
        Props  props = new Props("config.properties");
        controllerPath = props.getStr("controller.path");
        servicePath = props.getStr("service.path");
        serviceimplPath = props.getStr("serviceimpl.path");
        mapperInterfacePath = props.getStr("mapperinterface.path");
        mapperXmlPath = props.getStr("mapperxml.path");
        entityPath = props.getStr("entity.path");
        dsUrl = props.getStr("dsUrl");
        dsDriverName = props.getStr("dsDriverName");
        dsUsername = props.getStr("dsUsername");
        dsPassword = props.getStr("dsPassword");

    }
    /**
     * 数据源配置
     *
     * @return
     */
    private static DataSourceConfig datasourceConfig() {
        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setUrl(dsUrl);
        dsc.setDriverName(dsDriverName);
        dsc.setUsername(dsUsername);
        dsc.setPassword(dsPassword);
        return dsc;
    }

    /**
     * 全局配置
     *
     * @return
     */
    private static GlobalConfig globalConfig() {
        GlobalConfig gc = new GlobalConfig();
        gc.setAuthor("leon");
        gc.setFileOverride(false);
        gc.setSwagger2(false);
        gc.setOpen(false);
        gc.setServiceName("%sService");
        gc.setServiceImplName("%sServiceImpl");
        return gc;
    }

    /**
     * 配置包
     *
     * @return
     */
    private static PackageConfig packageConfig() {
        PackageConfig pc = new PackageConfig();
        pc.setParent("");
        pc.setController(pathToPackage(controllerPath));
        pc.setService(pathToPackage(servicePath));
        pc.setServiceImpl(pathToPackage(serviceimplPath));
        pc.setMapper(pathToPackage(mapperInterfacePath));
        pc.setEntity(pathToPackage(entityPath));
        return pc;
    }

    /**
     * 配置策略
     *
     * @return
     */
    private static StrategyConfig strategyConfig() {
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(".*");
        strategy.setControllerMappingHyphenStyle(false);
        strategy.setEntityTableFieldAnnotationEnable(true);
        return strategy;
    }

    /**
     * 自定义数据配置
     *
     * @return
     */
    private static InjectionConfig injectionConfig() {
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };
        return cfg;
    }

    /**
     * 配置输出模板
     *
     * @return
     */
    private static TemplateConfig templateConfig() {
        TemplateConfig templateConfig = new TemplateConfig();

        templateConfig.setXml(null);
        templateConfig.setServiceImpl(null);
        templateConfig.setController(null);
        templateConfig.setMapper(null);
        templateConfig.setXml(null);
        templateConfig.setService(null);
        templateConfig.setEntity(null);
        templateConfig.setEntityKt(null);
        return templateConfig;
    }

    private static List<FileOutConfig> selfOutConfig() {
        String controllerTemplatePath = "/templates/controller.java.ftl";
        ControllerOutConfig controllerOutConfig = new ControllerOutConfig(controllerTemplatePath, controllerPath);

        String serviceTemplatePath = "/templates/service.java.ftl";
        ServiceOutConfig serviceOutConfig = new ServiceOutConfig(serviceTemplatePath, servicePath);


        String mapperXmlTemplatePath="/templates/mapper.xml.ftl";
        MapperXmlOutConfig mapperXmlOutConfig = new MapperXmlOutConfig(mapperXmlTemplatePath, mapperXmlPath);

        String mapperInterfaceTemplatePath = "/templates/mapper.java.ftl";
        MapperInterfaceOutConfig mapperInterfaceOutConfig = new MapperInterfaceOutConfig(mapperInterfaceTemplatePath, mapperInterfacePath);

        String entityTemplatePath = "/templates/entity.java.ftl";
        EntityOutConfig entityOutConfig = new EntityOutConfig(entityTemplatePath, entityPath);

        String serviceimplTemplatePath = "/templates/serviceImpl.java.ftl";
        ServiceImplOutConfig serviceImplOutConfig = new ServiceImplOutConfig(serviceimplTemplatePath, serviceimplPath);

        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(controllerOutConfig);
        focList.add(serviceImplOutConfig);
        focList.add(serviceOutConfig);
        focList.add(mapperXmlOutConfig);
        focList.add(mapperInterfaceOutConfig);
        focList.add(entityOutConfig);
        return focList;
    }

    /**
     * 控制某些类是否生成的时候覆盖
     * @return
     */
    private static IFileCreate fileCreate(){
        return new FileCreate();
    }

    /**
     * 把path映射为package
     * @param path
     * @return
     */
    private static  String pathToPackage(String path) {
        int startIndex = path.indexOf("java")+5;
        return path.trim().substring(startIndex, path.length()).replace("\\",".");
    }
}
